package bean;

import bean.note.Bean;
import bean.Interceptor.FieldInterceptor;
import bean.Interceptor.Interceptor;
import bean.note.FieldsBean;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

public class BeanFactory {

    private List<Interceptor> fieldInterceptors = Arrays.asList(new FieldInterceptor());




    BeanFactory parent;


    public BeanFactory(BeanFactory parent) {
        this.parent = parent;
    }

    public BeanFactory() {
    }

    private List<BeanDefinition> bean = new ArrayList<>();

    public void register(Class config ) throws InstantiationException, IllegalAccessException {

        Object o = config.newInstance();

        Method[] methods = config.getDeclaredMethods();

        for (Method method : methods) {
            method.setAccessible(true);
            Bean annotation = method.getAnnotation(Bean.class);
            String name = method.getName();
            if (annotation != null){
                if (!annotation.value().isEmpty()){
                    name = annotation.value();
                }
                bean.add(new BeanDefinition(name,o,method));
            }
        }





    }

    private Map<String,Object> map = new HashMap<>();

    private Object newObj(BeanDefinition definition) throws IllegalAccessException {
        Object o = map.get(definition.getName());
        if ( o != null){
            return o;
        }
        Object a =  definition.newObj(this);
        map.put(definition.getName(), a);
        for (Interceptor interceptor : fieldInterceptors) {
           a =  interceptor.filter(a,this);
        }

        return a;

    }

    public Object getBean(String name) throws IllegalAccessException {

        if(parent != null){
            try {
                Object bean = parent.getBean(name);
                if(bean != null) return bean;
            }catch (Exception e){
                throw new RuntimeException("不存在Bean");
            }

        }
        for (BeanDefinition definition : bean) {
            if (definition.getName().equals(name)){
                return newObj(definition);
            }
        }
        throw new RuntimeException("不存在Bean");
    }

    public Object getBean(Class c) throws IllegalAccessException {

        for (BeanDefinition definition : bean) {
            if (c.isAssignableFrom(definition.getType())){
                return newObj(definition);
            }
        }
        throw new RuntimeException("不存在Bean");
    }

}
